function AdminOverride(ply)
	if (ply.AdminOverride) then
		return true
	else
		return false
	end
end

function SetCfgAdmin(ply,args)
	if (ply:IsAdmin() || ply:IsSuperAdmin()) then
		if (ply.AdminOverride == true) then
			ply.AdminOverride = false
			ply:PrintMessage(HUD_PRINTTALK, "Admin prop protection disabled.")
		else
			ply.AdminOverride = true
			ply:PrintMessage(HUD_PRINTTALK, "Admin prop protection enabled.")
		end
	end
end
concommand.Add( "propprotect_admin", SetCfgAdmin )

function NotifyPlayer( ply, msg )
	if (!timer.IsTimer(ply:SteamID() .. msg)) then
		timer.Create(ply:SteamID() .. msg, 5, 1, timer.Remove, ply:SteamID() .. msg)
		ply:PrintMessage( 2, msg );
		ply:SendLua( "GAMEMODE:AddNotify(\"" .. msg .. "\", " .. 1 .. ", " .. 3 .. ")" );
	end
end

local function PlayerSpawnedProp(ply, model, ent)
	ent.OwnerPly = ply
	ent.UniqueID = ply:UniqueID()
end
hook.Add("PlayerSpawnedProp", "playerspawnedprop", PlayerSpawnedProp)

local meta = FindMetaTable("Entity")
function meta:GetTheOwner()
	if ValidEntity(self.OwnerPly) then
		return self.OwnerPly
    elseif self.dt && ValidEntity(self.dt.Player) then
		return self.dt.Player
		//this is for sandbox based stuff.
	else
		return ents.GetByIndex(0)
	end
end

function IsPropProtected(ply1, ply2)
	if(ValidEntity(ply1) || ValidEntity(ply2)) then return false end
	
	if tonumber(ply1:GetInfo("rpdm_propprotect_"..ply2:UniqueID()))==1 && tonumber(ply2:GetInfo("rpdm_propprotect_"..ply1:UniqueID()))==1 then
		return true
	else
		return false
	end
end

function GM:PhysgunPickup(ply, ent)
	if AdminOverride(ply) then return true end
	
	if ent:IsWeapon() then 
		return true
	elseif ent.PhysgunPickup then //let the sent decide
		return ent:PhysgunPickup(ply)
	elseif ent:GetTheOwner() == ply then
		return true
    elseif IsPropProtected(ply, ent:GetTheOwner()) then
        return true
	else //a player, npc, door, etc
		if (!ent:GetTheOwner():IsPlayer()) then
			NotifyPlayer(ply, "This prop belongs to the world!" )
		else
			NotifyPlayer(ply, "This prop belongs to " .. ent:GetTheOwner():Nick() )
		end
		return false
	end
end

function GM:GravGunPickupAllowed(ply, ent)
	if AdminOverride(ply) then return true end
	
    if ent:IsWorld() then return false end
	
    if ent:IsWeapon() then 
		return true
	elseif ent.GravGunPickupAllowed then
		return ent:GravGunPickupAllowed(ply)
	elseif ent:GetTheOwner() == ply then
		return true
    elseif IsPropProtected(ply, ent:GetTheOwner()) then
        return true
	else
		if (!ent:GetTheOwner():IsPlayer()) then
			NotifyPlayer(ply, "This prop belongs to the world!" )
		else
			NotifyPlayer(ply, "This prop belongs to " .. ent:GetTheOwner():Nick() )
		end
		return false
	end
end

function GM:GravGunPunt(ply, ent)	
	if AdminOverride(ply) then return true end
	
	if ent.GravGunPunt then
		return ent:GravGunPunt(ply, ent)
	elseif ent:GetTheOwner() == ply then
		return true
    elseif IsPropProtected(ply, ent:GetTheOwner()) then
        return true
	else
		if (!ent:GetTheOwner():IsPlayer()) then
			NotifyPlayer(ply, "This prop belongs to the world!" )
		else
			NotifyPlayer(ply, "This prop belongs to " .. ent:GetTheOwner():Nick() )
		end
		return false
	end
end

local function CanTool(ply, tr, toolmode)
	if AdminOverride(ply) then return true end
	
	local owner2 = ply
	local subtrace = tr.Entity
	if (tool=="slider" || tool=="hydraulic" || tool=="muscle" || tool=="winch") then
		subtrace.start = tr.HitPos
		subtrace.endpos = subtrace.start + (trace.HitNormal * 16385)
		if ValidEntity(trace.Entity) then
			subtrace.filter = { ply, trace.Entity }
		else
			subtrace.filter = ply
		end
		subtrace = util.TraceLine(subtrace)
		if ValidEntity(subtrace.Entity) then
			owner2 = subtrace.Entity:GetTheOwner()
		end
	end
	
	if (!ValidEntity(tr.Entity) && !ValidEntity(subtrace.Entity)) then return true end
	
	if (owner2 == tr.Entity:GetTheOwner() || IsPropProtected(ply, owner2)) then print("debug") return true end
	
	if (tr.Entity:GetTheOwner() != ply || !IsPropProtected(ply, tr.Entity:GetTheOwner())) && !tr.HitWorld then
		if (!tr.Entity:GetTheOwner():IsPlayer()) then
			NotifyPlayer(ply, "This prop belongs to the world!" )
		else
			NotifyPlayer(ply, "This prop belongs to " .. tr.Entity:GetTheOwner():Nick() )
		end
		return false
	end
end
hook.Add("CanTool", "cantool", CanTool)

hook.Add("OnPhysgunReload", "onphysgunreload", function() return false end)

local function PlyConnectPP(ply)
	if timer.IsTimer("PPClear_"..tostring(ply:UniqueID())) then
		ply:PrintMessage(HUD_PRINTTALK, "Welcome back. Your props are still here.")
		timer.Destroy("PPClear_"..tostring(ply:UniqueID()))
		for k, v in pairs(ents.GetAll()) do
			if v.UniqueID==ply:UniqueID() then
				v.OwnerPly = ply
			end
		end
	end
end
hook.Add("PlayerInitialSpawn", "PropProtectPlyConnect", PlyConnectPP)

local function PlyDisconnectPP(ply)
	timer.Create("PPClear_"..tostring(ply:UniqueID()), 300, 1, PPClearProps, ply:UniqueID(), ply:Nick())
	for k, v in pairs(ents.GetAll()) do
		if v.UniqueID==ply:UniqueID() then
			v.OwnerPly = ents.GetByIndex(0)
		end
	end
end
hook.Add("PlayerDisconnected", "PropProtectPlyDisconnect", PlyDisconnectPP)

function PPClearProps(ownerid, name)
	if (ownerid == "EVERYONE") then
		for k, v in pairs(ents.GetAll()) do
			if v.UniqueID!=nil && !ValidEntity(player.GetByUniqueID(v.UniqueID)) then
				v:Remove()
			end
		end
	else
		for k, v in pairs(ents.GetAll()) do
			if v.UniqueID==ownerid then
				v:Remove()
			end
		end
	end
	
	for k, v in pairs(player.GetAll()) do
		v:PrintMessage(HUD_PRINTTALK, name.."'s props have been removed")
	end
end

function ClearAllDisconnectedProps(ply)
	if ply:IsAdmin() || ply:IsSuperAdmin() then
		PPClearProps("EVERYONE", "All disconnected player")
	end
end
concommand.Add( "propprotect_clearoldprops", ClearAllDisconnectedProps ) 

function ClearAllPlyProps(ply, cmd, args)
	if ply:IsAdmin() || ply:IsSuperAdmin() then
		local target = FindPlayer(args[1])
		if(target) then
			for k, v in pairs(ents.GetAll()) do
				if v:GetTheOwner()==target then
					v:Remove()
				end
			end
			for k, v in pairs(player.GetAll()) do
				v:PrintMessage(HUD_PRINTTALK, target:Nick().."'s props have been removed by: ".. ply:Nick())
			end
		else
				ply:PrintMessage( 2, "Did not find player: " .. args[1] );
		end
	end
end
concommand.Add( "propprotect_clearprops", ClearAllPlyProps ) 
